classdef TreeWidget <handle
    %TreeWidget handles the data of Input grids, computational grids and
    %Output data (points, lines, ...) displayed inside a Tree Panel and
    %Property grid.

% This file is part of CISNE.
%
%     CISNE is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     any later version.
%
%     CISNE is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%     GNU General Public License for more details.
%
%     You should have received a copy of the GNU General Public License
%     along with CISNE.  If not, see <http://www.gnu.org/licenses/>.

% Copyright 2011. Jose Maria Garcia-Valdecasas Bernal
    
    properties (SetAccess = public)%(SetAccess = private, Hidden=true)
        m_tree=[];
        m_gridmodel=[];
        m_gridList=[];
        m_grids=[];
        m_actualGrid=[];
        m_output=[];
        m_figure=[];
        m_jstr=java.lang.Class.forName('java.lang.String',true,...
            java.lang.Thread.currentThread().getContextClassLoader());
        m_jnum=java.lang.Class.forName('java.lang.Float', true,...
            java.lang.Thread.currentThread().getContextClassLoader());
        m_jint=java.lang.Class.forName('java.lang.Integer',true,...
            java.lang.Thread.currentThread().getContextClassLoader());
        m_jbool=java.lang.Class.forName('java.lang.Boolean', true,...
            java.lang.Thread.currentThread().getContextClassLoader());

    end
    
    methods
        function obj=TreeWidget(parent)
            if ishandle(parent)
                handles=guidata(parent);
                obj.m_figure=handles.figure1;
                clear handles;
                %get parent size to fit widget inside parent
                aux=get(parent,'Position');
                width=aux(3)-4; % 2pixels margin
                height=floor(aux(4)/2-6);
                                               
                % create property grid
                obj.m_gridList = java.util.ArrayList();
                obj.m_gridmodel = com.jidesoft.grid.PropertyTableModel(obj.m_gridList);
                obj.m_gridmodel.expandAll();
                grid = com.jidesoft.grid.PropertyTable(obj.m_gridmodel);
                pane = com.jidesoft.grid.PropertyPane(grid);
                pane.setShowToolBar(false);
                pane.setOrder(2);
                javacomponent(pane, [2 2 width height],parent);

                hModel = handle(obj.m_gridmodel, 'CallbackProperties');
                set(hModel, 'PropertyChangeCallback', @obj.onPropertyChangeFcn);
                              
                
                %create data tree
                grids = uitreenode('v0',{'null','data'}, 'USER DATA',[], false);
                grids.add(uitreenode('v0',{'unselected','INPUT'},...
                    'Input Grids',[], false));
                grids.add(uitreenode('v0',{'unselected','COMPUTATIONAL'},...
                    'Computational Grids',[], false));
                grids.add(uitreenode('v0',{'unselected','CPOINTS'},...
                    'Control Points',[], false));
                
                [obj.m_tree, container] = uitree('v0','root',grids,...
                    'Parent',parent); % Parent is ignored
                % fix the uitree Parent
                set(container, 'Parent', parent,'Position',[2 height+4 width height]);
                obj.m_tree.expand(grids);
                
                set(obj.m_tree, 'NodeSelectedCallback', @obj.nodeSelectedFcn );
                               
            end
        end
                 
        
    end
    methods (Access = private)
        function nodeSelectedFcn(obj,tree,ev)
            nodes = tree.getSelectedNodes;
            node = nodes(1);
            elem=node.getValue;
            elem=char(elem(2));
            if isfield(obj.m_grids,obj.m_actualGrid)
                obj.saveGridData(obj.m_actualGrid);
            end
            if isfield(obj.m_grids,elem)
                obj.m_actualGrid=elem;
                obj.loadGridData(elem);
            else
                obj.m_gridList.clear();
                obj.m_gridmodel.refresh();
            end
        end
        
        onPropertyChangeFcn(obj,model, event);
         
    end
    methods 
        loadGridData(obj,grid);
        saveGridData(obj,grid);
        
        function node=currentNode(obj)
            %get name of current node in case DisplayWidget needs it.
            nodes = obj.m_tree.getSelectedNodes;
            if ~isempty(nodes)
                node = nodes(1);
                node=node.getValue();
                node=char(node(2));
            else
                node=[];
            end
        end
        
        function val=getValue(obj,data,grid)
            if nargin==2
                grid=obj.m_actualGrid;
            end
            gridData=obj.m_grids.(grid);
            val=gridData{~cellfun(@isempty,strfind(gridData(:,1),data)),4};
        end
        
        function setValue(obj,data,val,grid)
            if nargin ==3
                grid=obj.m_actualGrid;
            end
            gridData=obj.m_grids.(grid);
            obj.m_grids.(grid){~cellfun(@isempty,strfind(gridData(:,1),data)),4}=val;
            
            if strcmp(grid,obj.m_actualGrid)
                obj.loadGridData(grid);
            end
        end
        
        addInputGrid(obj,type,name);
        addCompGrid(obj,parent,name);
        addControlPoint(obj,name);
        
        Points=getControlPoints(obj);
        CGrids=getCompGrids(obj);
        IGrids=getInputGrids(obj);
        
        function selectGrid(obj,grid)
            root=obj.m_tree.Root();
            child=getNodeByType(obj,root,grid);
            obj.m_tree.setSelectedNode(child);            
        end
        
        function grid=getNodeByName(obj,parent,node)
            if get(parent,'ChildCount')>0
                for j=0:get(parent,'ChildCount')-1
                    child=parent.getChildAt(j);
                    name=char(child.getName());
                    if (strcmp(name,node))
                        grid=child;
                        break
                    end
                    grid=obj.getNodeByName(child,node);
                    if ~isempty(grid)
                        break %if node has been found inside node's children
                    end
                end
            end
            if ~exist('grid','var')
                grid=[];
            end
        end
        
        function grid=getNodeByType(obj,parent,node)
            if get(parent,'ChildCount')>0
                for j=0:get(parent,'ChildCount')-1
                    child=parent.getChildAt(j);
                    kind=child.getValue();
                    kind=char(kind(2));
                    if (strcmp(kind,node))
                        grid=child;
                        break
                    end
                    grid=obj.getNodeByType(child,node);
                    if ~isempty(grid)
                        break %if node has been found inside node's children
                    end
                end
            end
            if ~exist('grid','var')
                grid=[];
            end
        end
        
        function list=getNodeNames(obj,parent,list)
            if get(parent,'ChildCount')>0
                for j=0:get(parent,'ChildCount')-1
                    child=parent.getChildAt(j);
                    kind=child.getValue();
                    kind=char(kind(2));
                    if (isempty(list))
                        list{1}=kind;
                    else
                        list={list{:},kind};
                    end
                    list=obj.getNodeNames(child,list);                    
                end
            end
        end
    end
    
end

